package ext.mango.utils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;

import mango.functions.FuncString;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Logger implements InvocationHandler {
    private static final ThreadLocal<String> LOG_INFO = new ThreadLocal<String>();
    
    public static void setInfo(Object... info) {
        StringBuilder sb = new StringBuilder();
        for (Object i : info) {
            sb.append(i).append("|");
        }
        LOG_INFO.set(sb.toString());
    }
    
    public static String getInfo() {
        return LOG_INFO.get();
    }
    
    public static void removeInfo() {
        LOG_INFO.remove();
    }
    
    private static HashMap<String, Log> logs = new HashMap<String, Log>();
    
    public static Log getLog(String name) {
        if (logs.get(name) != null) {
            return logs.get(name);
        }
        Log log = LogFactory.getLog(name);
        Logger logger = new Logger(log);
        Log wrapedlog = logger.getWrapedLog();
        logs.put(name, wrapedlog);
        return wrapedlog;
    }
    
    public static Log getLog(Class<?> clazz) {
        return getLog(clazz.getName());
    }

    private Log log;
    private Logger(Log log) {
        this.log = log;
    }

    public Log getWrapedLog() {
        return (Log) Proxy.newProxyInstance(log.getClass().getClassLoader(),
                new Class<?>[] { Log.class }, this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object obj = null;
        String m = method.getName();
        if ("trace".equals(m) 
                || "info".equals(m) 
                || "debug".equals(m)
                || "warn".equals(m)
                || "error".equals(m)
                || "fatal".equals(m)) {
            if (!FuncString.isBlank(Logger.getInfo())) {
                args[0] = Logger.getInfo() + args[0].toString();
            }
            obj = method.invoke(log, args);
        }
        else {
            obj = method.invoke(log, args);
        }
        return obj;
    }
}
